---
slug: mobx #路径，不能重复
title: mobx # 标题
authors: [] # 作者，在authors.yml配置
tags: [facebook, hello, docusaurus] # 标签，在tags.yml配置
toc_min_heading_level: 2 # 最小展示标题
toc_max_heading_level: 5 # 最大展示标题
---
* `mobx5` 可以运行在任何支持ES6 proxy的浏览器
* `mobx6` 移除装饰器

:::info
> 函数式组件不能直接使用observer装饰器,但是类组件可以

#### 类组件
```jsx

@observer
class Basic extends React.Component{
    render(){
        //.....
    }
}

```

#### 函数式组件
```jsx
const Basic =  observer(() =>{
    const basic = useContext(MobXProviderContext).basic;
    console.log("basic", basic);
    return (
        <>
        </>
    );
})

```
:::

## `mobx`
> js需要babel配置装饰器，但是我没整好

### 安装点必要依赖
* `mobx`
```shell
npm install mobx
```

* `mobx-react`

```shell
npm install mobx-react
```

### 使用

* `observable` : 定义可监测的公共状态
    * 只有变成可监测的后续监测机制才会生效
* `action` : 定义状态变更触发的事件

```jsx
import React from 'react';
import { observable, action, makeObservable } from "mobx";
import { Button } from "antd";
import { observer } from "mobx-react";
class State {
    constructor() {
        makeObservable(this, {
            num: observable,
            change: action
        });
    }

    num = 10;

    change() {
        this.num++;
        console.log(this.num);
    }
}

const state = new State();
const MobxComp  = observer(()=>{
        return (
            <div>
                <div>数量: {state.num}</div>
                <div>
                    <Button onClick={() => state.change()}>+</Button>
                </div>
            </div>
        );
})

export default MobxComp;
```

#### `action.bound`

> 此时`action`是报错的，因为拿到了setTimeOut里面的this,那个this指向windows，但是严格模式变成了undefined


```jsx
import React from 'react';
import {observable, action, makeObservable} from "mobx";
import { observer } from "mobx-react";

class State {
    constructor() {
        makeObservable(this, {
            num: observable,
            change: action
        });
    }

    num = 10;

    change() {
        console.log(this);//undefined
        this.num++;
        console.log(this.num);
    }
}




const state = new State();

const MobxComp  = observer(()=>{
    setTimeout(()=>{
        let fun = state.change;
        fun();
    },2000)

        return (
            <>
            </>
        );
})

export default MobxComp;
```

> 因此我们变成`action.bound`就解决了,这样`this`就是当前类的实例

```js

makeObservable(this, {
            num: observable,
            change: action.bound
        });
```

### `autorun`

> 会先执行一次，当监测值(autorun回调内部依赖的被标为`observable`的公共状态)发生改变时候自动触发callBack执行

```jsx
import React from 'react';
import {observable, makeObservable, autorun} from "mobx";
import { observer } from "mobx-react";

const MobxComp  = observer(()=>{
    class State {
        constructor() {
            makeObservable(this, {
                num: observable
            });
        }

        num = 10;
    }
    const state = new State();
    autorun(() => {
        //1.初次执行一次
        //2.setTimeOut两秒后修改
        console.log(state.num,'autorun');
    })

    setTimeout(()=>{
        state.num = 200;
    },2000)

        return (
            <>
            </>
        );
})

export default MobxComp;

```

#### 如果不是action修改状态的话，修改几次则autorun执行几次

**此例先不计算`autorun`初始执行那一次**

```js
//。。。。。上面的略，state的x,y当然要observable了

autorun(()=>{
    console.log(state.x,state.y);
})

setTimeout(()=>{
    state.x = 100;//autorun第一次执行，因为autorun内部依赖了x
    state.x = 200//autorun第二次执行,因为autorun内部依赖了y
})

```

#### 如果`action`修改的话则只执行一次

```jsx
import React from 'react';
import {observable, makeObservable, autorun,action} from "mobx";
import { observer } from "mobx-react";

const MobxComp  = observer(()=>{
    class State {
        constructor() {
            makeObservable(this, {
                num: observable,
                change:action
            });
        }

        x = 10;
        y = 10;
        change(){
            this.x++;
            this.y++;//总共执行一次
        }
    }
    const state = new State();
    autorun(() => {

        console.log(state.x,state.y);
    })

        return (
            <>
            </>
        );
})

export default MobxComp;

```


### `reaction`

> 第一次不会执行，只有监听的对象变化了才会执行

```js
reaction(
    ()=>[state.num],//监听的对象
    ()=>{
        console.log(state.num,'reaction');//监听对象变更后触发的回调函数
    }
)

```


```jsx
import React from 'react';
import {observable, action, makeObservable,reaction} from "mobx";
import { Button } from "antd";
import { observer } from "mobx-react";

class State {
    constructor() {
        makeObservable(this, {
            num: observable,
            change: action
        });
    }

    num = 10;

    change() {
        this.num++;
        console.log(this.num);
    }
}




const state = new State();
reaction(
    ()=>[state.num],
    ()=>{
        console.log(state.num,'reaction');
    }
)

const MobxComp  = observer(()=>{



        return (
            <div>
                <div>数量: {state.num}</div>
                <div>
                    <Button onClick={() => state.change()}>+</Button>
                </div>
            </div>
        );
})

export default MobxComp;
```

#### 启用严格模式，必须得通过`action`修改`observable`状态

:::warning
不报错，我也不懂为什么？？？？
:::

```jsx

configure({
    enforceActions: 'observed'//强制使用action方式修改状态
})

class State {
    constructor() {
        makeObservable(this, {
            num: observable,
            change: action
        });
    }

    num = 10;

    change() {
        this.num++;
    }
}




const state = new State();

const MobxComp  = observer(()=>{

    setTimeout(()=>{
        state.num = 100;
    },2000)

        return (
            <>
            </>
        );
})

export default MobxComp;


```

#### 就是不想写action怎么办？
>从`mobx`中解构一个`runInAction`

**在`runInAction`里面修改`observable`状态**
```jsx
runInAction(()=>{
    //TODO do something
})

```



### ts装饰器配置mobx

> 对于装饰器而言,makeObservable(this)这句是必需的,否则组件会不刷新

#### store

```ts
import {makeObservable, observable, action, configure, runInAction} from "mobx";
import {Component} from "react";
configure({
    enforceActions: 'always',
});

export default class BasicStore {

    constructor() {
        makeObservable(this);//这个是必须的
    }

    @observable
    num = 0;

    @action
    change(count:number){
        console.log(count);
        runInAction(()=>{
            this.num+=count;//异步操作需要在runInAction里面执行
        })
    }



}

```